/***
 * Copyright (c) 2021-2031 murenchao
 * fig is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.software.fig.libs

import java.io.Serializable
import java.util.ArrayList
import java.util.HashSet
import java.util.List
import java.util.Map
import java.util.Set
import java.util.concurrent.ConcurrentHashMap
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.ToString

@Accessors
@ToString
class DataFrame implements Serializable {
	ConcurrentHashMap<Object, Series> dfmap = new ConcurrentHashMap<Object, Series>();

	new(Object data) {
		if (data instanceof List) {
			if (data.size > 0 && data.get(0) instanceof List) {
				for (i : 0 .. data.size - 1) {
					var obj = data.get(i)
					if (obj instanceof List) {
						val columns = newArrayList()
						data.forEach [ v, j |
							columns.add(String.valueOf(j))
						]
						init(obj, null, columns, null, null)
					}
				}
			} else if (data.size > 0 && data.get(0) instanceof Map) {
				var columns = (data as List<Map<String, Object>>).map [ m |
					return m.keySet
				]
				var list = new ArrayList<Set<String>>()
				list.add(new HashSet<String>())
				list.addAll(columns)
				var nl = list.reduce[p1, p2|p1.addAll(p2) return p1]
				var values = (data as List<Map<String, Object>>).map [ m |
					return m.values.toList
				]
				init(values, null, nl.toList, null, null)
			}
		}
	}

	new(Object data, List<Object> index, List<String> columns, Class<?> dtype, Boolean copy) {
		init(data, index, columns, dtype, copy)
	}

	def init(Object data, List<Object> index, List<String> columns, Class<?> dtype, Boolean copy) {
		if (data instanceof List) {
			for (j : 0 .. columns.size - 1) {
				var newSeries = newArrayList()
				for (i : 0 .. data.size - 1) {
					var ldata = (data.get(i) as List<?>)
					if(j < ldata.size){
						newSeries.add(ldata.get(j))
					}else{
						newSeries.add(Series.NaN)
					}
				}
				dfmap.put(columns.get(j), new Series(newSeries))
			}
		}
	}

	def static void main(String[] args) {
		var r = #[#["a", 1], #["b", 2]]
		var a = new DataFrame(r, null, #["site", "age"], null, null)
		println(a)
		var r2 = #[#{"a" -> 1, "b" -> 2}, #{"a" -> 3, "b" -> 4, "c" -> 5}]
		var a2 = new DataFrame(r2)
		// var a = new DataFrame(newArrayList(newArrayList(1, 2, 3, 4, 5), newArrayList(6, 7, 8, 9, 10)))
		println(a2)
	}
}
